// 文件名：select_echo_server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

#define PORT 8888
#define MAX_CLIENTS  FD_SETSIZE
#define BUF_SIZE     1024

int main() {
    int listen_fd, conn_fd, sock_fd;
    int max_fd;
    int client_fds[MAX_CLIENTS];
    fd_set all_set, read_set;
    char buf[BUF_SIZE];
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t cli_len;
    int i, n;

    // 1. 创建监听 socket
    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd < 0) {
        perror("socket error");
        exit(1);
    }

    // 2. 绑定端口
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
    serv_addr.sin_port = htons(PORT);

    if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("bind error");
        exit(1);
    }

    // 3. 开始监听
    if (listen(listen_fd, 10) < 0) {
        perror("listen error");
        exit(1);
    }

    // 初始化 client 列表
    for (i = 0; i < MAX_CLIENTS; i++) client_fds[i] = -1;

    FD_ZERO(&all_set);
    FD_SET(listen_fd, &all_set);
    max_fd = listen_fd;

    printf("Echo server running on port %d...\n", PORT);

    while (1) {
        read_set = all_set; // 每轮都重置读集合
        int ready_n = select(max_fd + 1, &read_set, NULL, NULL, NULL);
        if (ready_n < 0) {
            perror("select error");
            exit(1);
        }

        // 4. 有新连接
        if (FD_ISSET(listen_fd, &read_set)) {
            cli_len = sizeof(cli_addr);
            conn_fd = accept(listen_fd, (struct sockaddr *)&cli_addr, &cli_len);
            if (conn_fd < 0) {
                perror("accept error");
                continue;
            }

            printf("New connection: %s:%d\n",
                   inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));

            // 加入 client_fds
            for (i = 0; i < MAX_CLIENTS; i++) {
                if (client_fds[i] < 0) {
                    client_fds[i] = conn_fd;
                    break;
                }
            }

            if (i == MAX_CLIENTS) {
                fprintf(stderr, "Too many clients\n");
                close(conn_fd);
                continue;
            }

            FD_SET(conn_fd, &all_set);
            if (conn_fd > max_fd) max_fd = conn_fd;

            if (--ready_n <= 0) continue;
        }

        // 5. 遍历所有客户端 socket
        for (i = 0; i < MAX_CLIENTS; i++) {
            sock_fd = client_fds[i];
            if (sock_fd < 0) continue;

            if (FD_ISSET(sock_fd, &read_set)) {
                // 接收数据
                n = read(sock_fd, buf, BUF_SIZE);
                if (n <= 0) {
                    // 客户端关闭连接
                    printf("Client disconnected: fd %d\n", sock_fd);
                    close(sock_fd);
                    FD_CLR(sock_fd, &all_set);
                    client_fds[i] = -1;
                } else {
                    // 回显数据
                    write(sock_fd, buf, n);
                }

                if (--ready_n <= 0) break;
            }
        }
    }

    return 0;
}

